home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / graphics / plotter.arj / PLOTTER.C < prev    next >
Text File  |  1993-08-06  |  18KB  |  635 lines

  1. /* PLOTTER.C */
  2.  
  3. #include <conio.h>
  4. #include <ctype.h>
  5. #include <dos.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <graphics.h>
  10. #include <math.h>
  11.  
  12. #define LEFT     -75
  13. #define RIGHT    -77
  14.  
  15. #define MAX(x,y)  (x)>(y) ? x : y
  16. #define MIN(x,y)  (x)<(y) ? x : y
  17.  
  18.  /* for dimensioning horizons, assume VGA max  */
  19. #define HSCREEN 640
  20. #define VSCREEN 480
  21.  /* upper bound on x- and z-divisions */
  22. #define MAXDIV  101
  23.  
  24. int numX, numZ;
  25. float X[MAXDIV], Z[MAXDIV];
  26. float Y[MAXDIV][MAXDIV];        /* Y[j][i] = f(X[i],Z[j]) */
  27. int theta0, alpha0;             /* rotation angles, degrees */
  28. float theta, alpha;             /* rotation angles, radians */
  29. int left, top, right, pbot;     /* plot window limits */
  30. char filename[30];              /* data file */
  31. int loaded = 0;                 /* 'function loaded' flag */
  32. int sxmax, symax;               /* maximum,minimum screen coordinates */
  33. int start, end;                 /* cursor start and end lines */
  34. char title[80];                 /* function name (formula, etc. */
  35. float xpmin, xpmax, ypmin, ypmax;       /* extreme transformed screen values */
  36. int eflag;                      /* if set, use exact max/min in scale() */
  37.  
  38. char *item[] = {" Load File ", " Viewpoint ", " Plot ", " Quit "};
  39. int len[4], pos[4], th0, tw0, mtop, mbot, ttop, tbot;
  40. int v[8];                       /* for drawing windows */
  41.  
  42. int border = 7, bgrnd = 6;      /* menu color values */
  43.  
  44. int height[] = {40, 40};        /* menu heights */
  45. int width[] = {300, 144};       /* and widths */
  46. int a0, b0, c0, d0, a1, b1, c1, d1; /* menu corners */
  47. int current;                    /* menu current option */
  48. void *buffer;                   /* for saving screen under windows */
  49.  
  50. /* function prototypes */
  51. int
  52. coeff(float v, float w, float v0, float w0, double *c1, double *c2),
  53. get_angles(),
  54. get_file(),
  55. getint(int n, char *s, int vi[]),
  56. getkey(void),
  57. getstr(char *s, int len),
  58. init_graphics(),
  59. normal_exit(void),
  60. scale();
  61.  
  62. extern int setup_xform(float, float); /* defined in hlplot.c */
  63.  
  64. /* varibles and arrays defined in hlplot.c */
  65. extern int Upper[HSCREEN],Lower[HSCREEN];  /* horizon arrays used in hlplot */
  66. extern int Xleft,Xright,Yleft,Yright;  /* used in hlplot to track edges */
  67. extern double ax, bx, ay, by;          /* scaling constants */
  68. extern double a00, a01, a11, a20, a21; /* entries in transformation matrix */
  69.  
  70. main()
  71. {
  72.   unsigned size1, size2, size;
  73.   int ltr[] = {'l', 'v', 'p', 'q'};
  74.   int i, c, selection;
  75.  
  76.   get_cursor(&start, &end);     /* save cursor shape */
  77.   init_graphics();              /* initialize graphics for later use */
  78.   barmenu(0);
  79.   top = mbot + 3;
  80.   left = 0;
  81.   right = sxmax, pbot = symax - 48;
  82.   ttop = pbot + 1;
  83.   tbot = symax;
  84.   a0 = pos[0];
  85.   b0 = mbot + 4;
  86.   c0 = a0 + width[0];
  87.   d0 = b0 + height[0];
  88.   a1 = pos[1];
  89.   b1 = mbot + 4;
  90.   c1 = a1 + width[1];
  91.   d1 = b1 + height[1];
  92.   size1 = imagesize(a0, b0, c0, d0);
  93.   size2 = imagesize(a1, b1, c1, d1);
  94.   size = size1 > size2 ? size1 : size2;
  95.   if ((buffer = malloc(size)) == NULL) {
  96.     closegraph();
  97.     printf("Not enough memory for buffer\n");
  98.     exit(1);
  99.   }
  100.   /* frame plot area and text area */
  101.   setcolor(15);
  102.   rectangle(left, top, right, pbot);
  103.   fill_text_area(7);
  104.  
  105. /* get initial file */
  106.   if (get_file()) {
  107.     norm(current);
  108.     loaded = 1;
  109.     fill_text_area(7);
  110.     put_text();                 /* print title, etc. */
  111.     current = 2;                /* return to 'Plot' */
  112.     high(current);
  113.   } else
  114.     putimage(a0, b0, buffer, COPY_PUT); /* restore screen under window */
  115.  
  116.   while (1) {
  117.     selection = -1;
  118.     switch (c = getkey()) {
  119.       case RIGHT:
  120.         norm(current);
  121.         if (current == 3)
  122.           current = 0;
  123.         else
  124.           current++;
  125.         high(current);
  126.         break;
  127.       case LEFT:
  128.         norm(current);
  129.         if (current == 0)
  130.           current = 3;
  131.         else
  132.           current--;
  133.         high(current);
  134.         break;
  135.       case 13:                  /* make selection when Enter key pressed */
  136.         selection = current;
  137.         break;
  138.       case 27:                  /* Esc is alternate exit key */
  139.         normal_exit();
  140.       default:                  /* if letter command, change highlight and
  141.                                  * select */
  142.         for (i = 0; i < 4; i++)
  143.           if (ltr[i] == c || ltr[i] - 32 == c) {
  144.             norm(current);
  145.             current = i;
  146.             high(current);
  147.             selection = current;
  148.             break;
  149.           }
  150.     }
  151.     if (selection >= 0) {
  152.       switch (selection) {
  153.         case 0:         /* Load File */
  154.           if (get_file()) {
  155.             norm(current);
  156.             loaded = 1;
  157.             fill_text_area(7);
  158.             put_text();         /* print title, etc. */
  159.             current = 2;        /* return to 'Plot' */
  160.             high(current);
  161.             break;
  162.           } else {
  163.             putimage(a0, b0, buffer, COPY_PUT); /* restore screen under
  164.                                                  * window */
  165.           }
  166.           break;
  167.         case 1:         /* 'Viewpoint' */
  168.           norm(current);
  169.           if (get_angles()) {
  170.             fill_text_area(7);
  171.             put_text();         /* to upgrade angle display */
  172.             current = 2;        /* return to 'Plot' */
  173.           } else
  174.             putimage(a1, b1, buffer, COPY_PUT);
  175.           high(current);
  176.           break;
  177.         case 2:         /* 'Plot' */
  178.           norm(2);
  179.           scale();
  180.           plot();
  181.           current = 1;          /* return to 'Viewpoint' */
  182.           high(current);
  183.           break;
  184.         case 3:         /* 'Quit' */
  185.           normal_exit();
  186.       }
  187.     }
  188.   }
  189. }
  190.  
  191. /* ============== alphabetical listing of demo functions ================= */
  192.  
  193. barmenu()
  194. {                               /* setup menu bar */
  195.   int i, lentotal = 0;
  196.   settextstyle(1, 0, 1);        /* triplex font for menu text */
  197.   tw0 = textwidth("H");
  198.   th0 = textheight("H");
  199.   mtop = 0;
  200.   mbot = th0 + 6;
  201.   for (i = 0; i < 4; i++) {
  202.     len[i] = textwidth(item[i]) + 4 * tw0;
  203.     lentotal += len[i];
  204.   }
  205.   pos[0] = (sxmax - lentotal) / 2;      /* center menu items */
  206.  
  207.   pos[1] = pos[0] + len[0];     /* starting x-values for items 0-3 */
  208.   pos[2] = pos[1] + len[1];
  209.   pos[3] = pos[2] + len[2];
  210.  
  211.   setcolor(15);                 /* bright white border */
  212.   setfillstyle(1, 7);           /* dull white interior */
  213.   bar3d(pos[0] - 2 * tw0, mtop, pos[3] + 6 * tw0, mbot, 0, 0);
  214.   setcolor(0);                  /* normal text color = black */
  215.   high(0);
  216.   norm(1);
  217.   norm(2);
  218.   norm(3);
  219. }
  220.  
  221. /* set scaling coefficients c1,c2 so that  c1*v +c2 = v0 and  c1*w + c2 = w0 */
  222. coeff(float v, float w, float v0, float w0, double *c1, double *c2)
  223. {
  224.   *c1 = (double) (w0 - v0) / (w - v);
  225.   *c2 = (double) (v0 - (*c1) * v);
  226. }
  227.  
  228. /*---------------------------------------------------------------------------*/
  229. /* Routine to center a string 'inside itself' */
  230. center(char *s)
  231. {
  232.   int i,n,k,ls,ts,ns;
  233.   char s1[81];
  234.  
  235.   n = strlen(s);
  236.   if (n > 80)
  237.     return 0;
  238.  
  239.   i = 0;
  240.   while(s[i] == ' ')
  241.     i++;
  242.   ls = i;
  243.  
  244.   i = n-1;
  245.   while(s[i] == ' ')
  246.     i--;
  247.   ts = n-i-1;
  248.   ns = n - (ls+ts);
  249.   k = (ls+ts)/2;
  250.  
  251.   for (i=0; i<k; i++)
  252.     s1[i] = ' ';
  253.   for (i=0; i<ns; i++)
  254.     s1[k+i] = s[ls+i];
  255.   for (i=k+ns; i<n; i++)
  256.     s1[i] = ' ';
  257.   s1[n] = '\0';
  258.   strcpy(s,s1);
  259.   return 1;
  260. }
  261.  
  262. /*---------------------------------------------------------------------------*/
  263. fill_text_area(int color)
  264. {
  265.   setfillstyle(SOLID_FILL, color);
  266.   v[0] = v[6] = v[8] = 0;
  267.   v[1] = v[3] = v[9] = ttop;
  268.   v[2] = v[4] = sxmax;
  269.   v[5] = v[7] = symax;
  270.   fillpoly(5, v);
  271. }
  272.  
  273. /*---------------------------------------------------------------------------*/
  274. get_angles()
  275. {
  276.   char s[12];
  277.   int vi[2];                    /* for input of theta and alpha */
  278.   int c;
  279.  
  280.   settextstyle(0, 0, 1);
  281.   getimage(a1, b1, c1, d1, buffer);
  282.   gwindow(a1 + 1, b1 + 1, c1 - 1, d1 - 1, bgrnd, border);
  283.   setcolor(15);
  284.   if (!loaded) {
  285.     outtextxy(a1 + 8, b1 + 11, "No file loaded");
  286.     outtextxy(a1 + 8, b1 + 24, "Press any key");
  287.     getch();
  288.     return 0;
  289.   }
  290.   outtextxy(a1 + 8, b1 + 10, "Angle THETA: ");
  291.   c = getgstr(a1 + 112, b1 + 10, s);
  292.   if (c == -1)                  /* escape pressed */
  293.     return 0;
  294.   if (c == 0) {                 /* empty entry */
  295.     gprintf(a1 + 112, b1 + 10, 15, "%d", theta0);
  296.     goto a0;
  297.   }
  298.   if (!s[0])
  299.     return 0;
  300.   theta0 = atoi(s);
  301. a0:
  302.   outtextxy(a1 + 8, b1 + 24, "Angle ALPHA: ");
  303.   c = getgstr(a1 + 112, b1 + 24, s);
  304.   if (c == -1)
  305.     return 0;
  306.   if (c == 0) {
  307.     gprintf(a1 + 112, b1 + 24, 15, "%d", alpha0);
  308.     goto a1;
  309.   }
  310.   if (!s[0])
  311.     return 0;
  312.   alpha0 = atoi(s);
  313. a1:
  314.   /* adjust sizes if necessary */
  315.   theta0 = theta0 < -45 ? -45 : theta0 > 45 ? 45 : theta0;
  316.   alpha0 = alpha0 < -45 ? -45 : alpha0 > 45 ? 45 : alpha0;
  317.   putimage(a1, b1, buffer, COPY_PUT);
  318.   return 1;
  319. }
  320.  
  321. /* --------------------------------------------------------------------- */
  322. get_cursor(int *start, int *end)
  323. {
  324.   _AH = 3;
  325.   _BH = 0;
  326.   geninterrupt(0x10);
  327.   *start = _CH;
  328.   *end = _CL;
  329. }
  330.  
  331. /* --------------------------------------------------------------------- */
  332. get_file()
  333. {
  334.   int i, j, c;
  335.   char *p, s[1];
  336.   FILE *fp;
  337.  
  338.   getimage(a0, b0, c0, d0, buffer);
  339.   gwindow(a0 + 1, b0 + 1, c0 - 1, d0 - 1, bgrnd, border);
  340.   setcolor(15);
  341.   outtextxy(a0 + 8, b0 + 5, "File : ");
  342.   if (getgstr(a0 + 64, b0 + 5, filename) <= 0)
  343.     return 0;
  344.   eflag = 0;
  345.   if ((p = strchr(filename, '/')) != NULL) {
  346.     eflag = 4;
  347.     *p = '\0';
  348.   }
  349.   fp = fopen(filename, "r+b");
  350.   if (fp == NULL) {
  351.     outtextxy(a0 + 8, b0 + 24, "File not found; Press any key.");
  352.     getch();
  353.     return 0;
  354.   }
  355.   strupr(filename);
  356.   outtextxy(a0 + 8, b0 + 25, "Reading file ...");
  357.   if (strstr(filename, ".ASC"))
  358.     read_asc_data(fp);
  359.   else
  360.     read_bin_data(fp);
  361.   fclose(fp);
  362.   theta0 = theta0 < -45 ? -45 : theta0 > 45 ? 45 : theta0;
  363.   alpha0 = alpha0 < -45 ? -45 : alpha0 > 45 ? 45 : alpha0;
  364.   putimage(a0, b0, buffer, COPY_PUT);   /* restore screen under window */
  365.   return 1;
  366. }
  367. /*-------------------------------------------*/
  368. read_bin_data(FILE *fp)
  369. {
  370.   int j;
  371.  
  372.   fread(title, sizeof(char), 70, fp);
  373.   title[70] = '\0';
  374.   center(title);
  375.   fread(&numX, sizeof(int), 1, fp);
  376.   fread(&numZ, sizeof(int), 1, fp);
  377.   fread(X, sizeof(float), numX, fp);
  378.   fread(Z, sizeof(float), numZ, fp);
  379.   for (j = 0; j < numZ; j++)
  380.     fread(&Y[j], sizeof(float), numX, fp);
  381.   fread(&theta0, sizeof(int), 1, fp);
  382.   fread(&alpha0, sizeof(int), 1, fp);
  383.  }
  384. /*-------------------------------------------*/
  385. read_asc_data(FILE *fp)
  386. {
  387.   int i,j;
  388.  
  389.   fread(title, sizeof(char), 70, fp);
  390.   title[70] = '\0';
  391.   center(title);
  392.   fscanf(fp, "%d %d", &numX, &numZ);
  393.   for (i = 0; i < numX; i++)
  394.     fscanf(fp, "%f", &X[i]);
  395.   for (j = 0; j < numZ; j++)
  396.     fscanf(fp, "%f", &Z[j]);
  397.   for (j = 0; j < numX; j++)
  398.     for (i = 0; i < numX; i++)
  399.       fscanf(fp, "%f", &Y[j][i]);
  400.   theta0 = alpha0 = 0;
  401.   if (!feof(fp))
  402.     fscanf(fp, "%d %d", &theta0, &alpha0);
  403.  }
  404.  
  405. /*---------------------------------------------------------------------------*/
  406. /*     extract n integer values from string s, put them in array vi[]        */
  407. getint(int n, char *s, int vi[])
  408. {
  409.   int cnt = 0;
  410.   char *p;
  411.  
  412.   if (n == 0)
  413.     return cnt;
  414.  
  415.   p = s;
  416.   while (cnt < n && *p) {
  417.     while (!isdigit(*p) && *p != '-')
  418.       p++;
  419.     vi[cnt] = atoi(p);
  420.     p++;
  421.     while (isdigit(*p))
  422.       p++;
  423.     cnt++;
  424.   }
  425.   return cnt;
  426. }
  427.  
  428. /*---------------------------------------------------------------------------*/
  429.  /* basic input loop feeder */
  430. getkey(void)
  431. {
  432.   int k;
  433.  
  434.   k = getch();
  435.   if (k == 0)
  436.     k = -getch();
  437.   return k;
  438. }
  439.  
  440. /* --------------------------------------------------------------------- */
  441. /* get user input (into array t[]), echo on screen at (x1,y1)            */
  442. /* eol stops input; backspace ok, no other editing functions implemented */
  443. /* for graphics modes only */
  444.  
  445. int
  446. getgstr(int x1, int y1, char *t)
  447. {
  448.   int x0 = x1, width = 8;
  449.   char *p, c, s1[2];
  450.  
  451.   p = t;
  452.   s1[1] = '\0';
  453.   moveto(x1, y1);
  454.  
  455.   while ((c = getch()) != '\r') {
  456.     if (c == 27)                /* leave if Esc pressed */
  457.       return -1;                /* to indicate abnormal exit */
  458.     if (isprint(c) && x1 < sxmax - width) {
  459.       s1[0] = c;
  460.       outtext(s1);
  461.       x1 = getx();
  462.       *p = c;
  463.       p++;
  464.     }
  465.     if (c == 8 && x1 > x0) {
  466.       x1 -= width;
  467.       p--;
  468.       moveto(x1, y1);
  469.       bar(x1, y1, x1 + width, y1 + width);
  470.     }
  471.   }
  472.   *p = '\0';
  473.   if (p == t)
  474.     return 0;                   /* no input */
  475.   return 1;                     /* normal exit */
  476. }
  477.  
  478. /* ---------------------------------------------------------------------- */
  479. /* graphics version of printf(); from Borland graphics demo BGIDEMO.C     */
  480. /* prints string at pixel location (x,y) in color c                       */
  481.  
  482. gprintf(int x, int y, int c, char *fmt,...)
  483. {
  484.   va_list argptr;
  485.   char str[140];
  486.  
  487.   va_start(argptr, fmt);
  488.   vsprintf(str, fmt, argptr);
  489.   setcolor(c);
  490.   outtextxy(x, y, str);
  491.   va_end(argptr);
  492. }
  493.  
  494. /* ---------------------- Set up graphics window ------------------------- */
  495. gwindow(x0, y0, z0, w0, bgrnd, border)
  496.   int x0, y0;                   /* upper left corner */
  497.   int z0, w0;                   /* lower right corner */
  498.   int bgrnd, border;            /* colors */
  499. {
  500.   int i;
  501.  
  502.   setcolor(border);
  503.   setlinestyle(SOLID_LINE, 0, THICK_WIDTH);     /* for borders of windows */
  504.   setfillstyle(SOLID_FILL, bgrnd);
  505.   v[0] = v[6] = v[8] = x0;
  506.   v[1] = v[3] = v[9] = y0;
  507.   v[2] = v[4] = z0;
  508.   v[5] = v[7] = w0;
  509.   fillpoly(5, v);
  510.   setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
  511. }
  512.  
  513. /*------------------------- part of menu system ---------------------------- */
  514.  
  515. high(int i)
  516. {
  517.   settextstyle(1, 0, 1);        /* triplex font for menu text */
  518.   setcolor(12);
  519.   outtextxy(pos[i], mtop + 1, item[i]);
  520.   settextstyle(0, 0, 1);        /* reset normal text */
  521. }
  522.  
  523. /*---------------------------------------------------------------------------*/
  524. init_graphics()
  525. {
  526.   int graphdriver = DETECT, graphmode;
  527.   char *pathtodriver = "c:\\tbc";
  528.  
  529.   registerbgifont(triplex_font);/* assuming in graphics.lib */
  530.   initgraph(&graphdriver, &graphmode, pathtodriver);
  531.   if (graphdriver != EGA && graphdriver != VGA) {
  532.     printf("This program requires EGA or VGA graphics.");
  533.     exit(1);
  534.   }
  535.   sxmax = getmaxx();
  536.   symax = getmaxy();
  537. }
  538.  
  539. /*------------------------- part of menu system ---------------------------- */
  540. norm(int i)
  541. {
  542.   settextstyle(1, 0, 1);        /* triplex font for menu text */
  543.   setcolor(0);
  544.   outtextxy(pos[i], mtop + 1, item[i]);
  545.   settextstyle(0, 0, 1);        /* reset normal text */
  546. }
  547.  
  548. /*---------------------------------------------------------------------------*/
  549. normal_exit(void)
  550. {
  551.   closegraph();
  552.   exit(0);
  553. }
  554.  
  555. /* ------------------------------------------------------------------------- */
  556. put_text()
  557. {
  558.   char s[80], view[22];
  559.   int tw;
  560.  
  561.   sprintf(s, " %s    Xdiv: %d, Zdiv: %d", filename, numX, numZ);
  562.   sprintf(view, "View angles: %d,%d", theta0, alpha0);
  563.   setcolor(0);                  /* black graphics text */
  564.   if (strlen(title))
  565.     outtextxy(12, ttop + 12, title);    /* print title */
  566.   outtextxy(4, ttop + 30, s);   /* print filename, divisions */
  567.   tw = textwidth(view) + 4 * tw0;
  568.   outtextxy(right - tw, ttop + 30, view);       /* print view angles  */
  569. }
  570.  
  571. /* ---------------- initialize scaling constants, etc. ----------------------*/
  572. scale()
  573. {
  574.   double deg2rad;
  575.   float x, y, z, x1, y1;
  576.   float t;
  577.   int i, j, deltaX, deltaZ;
  578.  
  579.   deg2rad = atan(1) / 45;
  580.   /* change angles from degrees to radians: */
  581.   theta = theta0 * deg2rad;
  582.   alpha = alpha0 * deg2rad;
  583.  
  584.   /* initialize various constants: */
  585.   setup_xform(theta, alpha);
  586.   Xleft = Yleft = Xright = Yright = -1;
  587.  
  588.   /* initialize horizon arrays */
  589.   for (i = 0; i < sxmax; i++) {
  590.     Upper[i] = 0;
  591.     Lower[i] = symax;
  592.   }
  593.  
  594.   /* find (approx) maximum and minimum x,y for the projection */
  595.   /* use deltaX and detaZ to limit number of xz-values checked */
  596.   xpmin = ypmin = 1e10;
  597.   xpmax = ypmax = -1e10;
  598.   if ((numX - 1) % 5 || (numZ - 1) % 5)
  599.     eflag = 4;                  /* don't approximate in this case */
  600.   deltaX = deltaZ = 5 - eflag;  /* eflag = 0 or 4; if set, check all levels */
  601.  
  602.   for (j = 0; j < numZ; j += deltaZ) {
  603.     z = Z[j];
  604.     for (i = 0; i < numX; i += deltaX) {
  605.       x = X[i];
  606.       y = Y[j][i];
  607.       x1 = a00 * x + a20 * z;
  608.       y1 = a01 * x + a11 * y + a21 * z;
  609.       if (x1 < xpmin)
  610.         xpmin = x1;
  611.       if (x1 > xpmax)
  612.         xpmax = x1;
  613.       if (y1 < ypmin)
  614.         ypmin = y1;
  615.       if (y1 > ypmax)
  616.         ypmax = y1;
  617.     }
  618.   }
  619.  
  620. /* set scaling constants so that graph fills viewport */
  621.   coeff(xpmin, xpmax, left + 15.0, right - 15.0, &ax, &bx);
  622.   coeff(ypmin, ypmax, pbot - 15.0, top + 15.0, &ay, &by);
  623. }
  624.  
  625. /*---------------------------------------------------------------------------*/
  626. showcursor()
  627. {
  628.   _AX = 0x0100;
  629.   _BX = 0;
  630.   _CH = (unsigned) start;       /* start, end = original values */
  631.   _CL = (unsigned) end;
  632.   geninterrupt(0x10);
  633. }
  634.  
  635.